"""
Copyright (C) 2008 Masahiro Nakao

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
"""

#import young
import math

def get_range(function):
    ary = [0] * 2
    MIN_RANGE = 0
    MAX_RANGE = 1
    
    if function == "Rastrigin" or function == "Rastrigin-1.0":
        ary[MIN_RANGE] = -5.12
        ary[MAX_RANGE] = 5.12
        
    elif function == "Ridge" or function == "Ridge-1.0":
        ary[MIN_RANGE] = -64.0
        ary[MAX_RANGE] = 64.0
        
    elif function == "Schwefel" or function == "Griewank" or function == "Griewank-1.0":
        ary[MIN_RANGE] = -512.0
        ary[MAX_RANGE] = 512.0
        
    elif function == "Rosenbrock":
        ary[MIN_RANGE] = -2.048
        ary[MAX_RANGE] = 2.048
         
    else:
        print "Error function name " + function
        exit (1)

    return ary

def evaluation(function, ary):
    value = 0
    
    if function == "Onemax":
        value = onemax(ary)
    elif function == "Rastrigin":
        value = rastrigin(ary)
    elif function == "Ridge":
        value = ridge(ary)
    elif function == "Ridge-1.0":
        value = ridge_1(ary)
    elif function == "Schwefel":
        value = schwefel(ary)
    elif function == "Griewank":
        value = griewank(ary)
    elif function == "Griewank-1.0":
        value = griewank_1(ary)
    elif function == "Rastrigin-1.0":
        value = rastrigin_1(ary)
    elif function == "Rosenbrock":
        value = rosenbrock(ary)
    else:
        print "Error function name " + function
        exit (1)
        
    return value

def onemax(ary):
    value = 0
    
    for i in ary:
        if i == 1:
            value += 1
    
    return -1 * value

def rastrigin(ary):
    value = 0.0
    
    for i in range(len(ary)):
        value += ary[i] * ary[i] - 10 * math.cos(2 * math.pi * ary[i])
        
    return 10 * len(ary) + value

def schwefel(ary):
    value = 0.0
    schw_ans = 418.9828872724336861210758797824382781982
    
    for i in range(len(ary)):
        value += ary[i] * math.sin(math.sqrt(math.fabs(ary[i])))
        
    return schw_ans * len(ary) - value

def rastrigin_1(ary):
    value = 0.0
    
    x = ary[:]
    
    for i in range(len(x)):
        x[i] -= 1.0
        
    for i in range(len(x)):
        value += x[i] * x[i] - 10 * math.cos(2 * math.pi * x[i])
        
    return 10 * len(x) + value

def griewank(ary):
    
    x = ary[:]
    d = 1.0
    e = 1.0
    
    for i in range(len(x)):
        d += x[i] * x[i] / 4000
        e *= math.cos(x[i] / math.sqrt(i + 1))
    
    return d - e

def griewank_1(ary):
    
    x = ary[:]
    for i in range(len(x)):
        x[i] -= 1.0
    
    d = 1.0
    e = 1.0
    
    for i in range(len(x)):
        d += x[i] * x[i] / 4000
        e *= math.cos(x[i] / math.sqrt(i + 1))
    
    return d - e

def ridge(ary):
    d = 0.0
    x = ary[:]

    for i in range(len(x)):
        p = 0.0
        for j in range(i+1):
            p += x[j]
        d += p * p
        
    return d

def ridge_1(ary):
    d = 0.0
    x = ary[:]

    for i in range(len(x)):
        x[i] -= 1.0

    for i in range(len(x)):
        p = 0.0
        for j in range(i+1):
            p += x[j]
        d += p * p
        
    return d

def rosenbrock(ary):
    d = 0.0
    
    for i in range(len(ary)-1):
        p = ary[i + 1] - ary[i] * ary[i]
        q = ary[i] - 1
        d += p * p * 100 + q * q;
        
    return d

if __name__ == '__main__':
    print "Func Name\tDesign Valiable"
    
    function_name = ["Rastrigin", "Rastrigin-1.0", "Ridge", "Ridge-1.0", "Schwefel", "Griewank", "Griewank-1.0", "Rosenbrock"]
    for n in function_name:
        print n + "\t" + str(get_range(n))
    
    print "--------------------------------------------------------------------"
    design_valiable=[[1.0, 1.0], [1.0, 1.0, 1.0], [0.99, 1.0, 1.0]]
    for v in design_valiable:
        for n in function_name:
            print n + "\t" + str(evaluation(n, v)) + "\t" + str(v)
        print "--------------------------------------------------------------------"
    
        